import {isDef} from "../../../shared/util";
import {isReservedTag} from "../../../platform/util";
import {VNode} from "../../../type/VNode";
import {createComponent} from "./create-component";
import {resolveAssets} from "../../global-api/assets";

/**
 * 对 children 数组进行标准化
 * @param {Array} children
 */
export function normalizeChildren (children) {
    for (let i=0; i<children.length; i++) {
        const node = children[i];
        if (!isDef(node) || (Array.isArray(node) && node.length === 0)) {
            children.splice(i,1);
            i --;
        }
        // 是数组，且数组内容不为 null
        if (Array.isArray(node) && node.length !== 0) {
            children.splice(i, 1, ...node);
            i --;
        }
    }
}

/**
 * 创建普通类型 HTML 节点的 VNode
 * @param context 上下文环境， Reactive 实例
 * @param tag 标签名称
 * @param data 生成的数据
 * @param children 孩子节点
 * @param options 配置项
 * @return {VNode} 创建好的 VNode
 * @private
 */
export function _createElement (context, tag, data, children, options) {
    // 对于 children 孩子节点进行正则化
    /**
     * 这里说一下为什么 children 需要正则化，
     * 因为 template 标签内的节点都会渲染在一个数组内，（因为 template 并不是一个真实的节点）
     * 需要把数组内的内容转移到 children 数组中
     *
     * 举个例子
     * [vnode1, vnode2, [vnode3, vnode4, vnode5], vnode6]
     * 变换为
     * [vnode1, vnode2, vnode3, vnode4, vnode5, vnode6]
     */
    normalizeChildren(children);
    // fixme 由于 v-key 怎么标记 [ vnode3, vnode4, vnode5 ] 这种节点呢，我选择不标记

    let Ctor = null;
    // 为组件节点
    if (!isReservedTag(tag) && tag !== "slot") {
        Ctor = resolveAssets('component', tag);
        if (isDef(Ctor)) {
            return createComponent(Ctor, context, tag, data, children, options);
        }
    }
    // 为非组件节点，或者未找到组件对应的模板内容
    // 生成该节点的 VNode 节点
    const vnode = new VNode(tag, data, children, undefined);
    vnode.context = context;
    // 将孩子节点的 parent 指向 vnode
    for (let i=0; i<children.length; i++) {
        children[i].parent = vnode;
    }
    return vnode;
}
